package com.opener.web.push.service.impl;

import com.opener.common.http.HttpResponse;
import com.opener.common.utils.Utils;
import com.opener.web.push.dao.PushAppDao;
import com.opener.web.push.dao.PushMsgConfDao;
import com.opener.web.push.dao.PushRecordDao;
import com.opener.web.push.model.*;
import com.opener.web.push.service.PushRecordService;
import com.opener.web.push.service.PushService;
import com.opener.web.service.sys.SysConfService;
import com.opener.web.spring.exception.DataException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by baboy on 25/07/2017.
 */
@Service
public class PushRecordServiceImpl implements PushRecordService {
    private Logger logger = LoggerFactory.getLogger(PushRecordServiceImpl.class);
    @Autowired
    private PushRecordDao pushRecordDao;
    @Autowired
    private PushAppDao pushAppDao;
    @Autowired
    private PushMsgConfDao pushMsgConfDao;
//    @Autowired
//    private PushService smsPushService;
    @Autowired
    @Qualifier("sendCloudPushService")
    private PushService sendCloudPushService;
    @Autowired
    @Qualifier("wechatPushService")
    private PushService wechatPushService;
    @Autowired
    @Qualifier("emailPushService")
    private PushService emailPushService;
    @Autowired
    private SysConfService sysConfService;

    private Map<String, PushService> servicePool;
    @Autowired
    protected ThreadPoolTaskExecutor taskExecutor;

    @PostConstruct
    public void init(){
        if(servicePool == null){
            servicePool = new HashMap<String, PushService>();
//            servicePool.put(PushApp.APP_SP_RL_SMS, smsPushService);
            servicePool.put(PushApp.APP_SP_SC_SMS, sendCloudPushService);
            servicePool.put(PushApp.APP_SP_WECHAT, wechatPushService);
            servicePool.put(PushApp.APP_SP_SC_EMAIL, emailPushService);
        }
    }

    @Override
    public boolean addPushRecord(PushRecord record) {
        boolean ret = pushRecordDao.addPushRecord(record) > 0;
        return ret;
    }

    @Override
    public boolean updatePushRecord(PushRecord record) {
        boolean ret = pushRecordDao.updatePushRecord(record)>0;
        return ret;
    }

    @Override
    public List<PushRecord> getPushRecords(PushRecordSearchArgs args){
        List<PushRecord> records = pushRecordDao.getPushRecords(args);
        return records;
    }


    public void addRecord(String appId, PushApp app, PushMsgConf msgConf, Map data, String to, String ip, boolean status, String errorMsg){
        PushRecord record = new PushRecord();
        record.setMsgType(app.getType());
        record.setAppId(appId);
        record.setTo(to);
        record.setAid(app.getId());
        record.setMsgId(msgConf.getId());
        record.setData(data);
        record.setIp(ip);
        record.setErrorMsg(errorMsg);
        record.setStatus(status ? PushRecord.PUSH_STATUS_SUCCESS : PushRecord.PUSH_STATUS_ERROR);
        pushRecordDao.addPushRecord(record);
    }
    public boolean check(String appId,int aid,String msgType, String to,int msgId , String ip){
        Map m =  sysConfService.getMapValue(msgType + "-policy");
        if (m == null){
            return true;
        }
        Map dayConf = (Map)m.get("day");
//        1、每个电话总发送量（不同模板） numPerMobile
//        2、每个客户ip总发送量（不同模板） numPerIp
//        3、每个模板发送量 numPerTpl
//        4、所有模板总发送量 totalOfTpl

        //检查渠道来源
        Map appConfs = (Map)dayConf.get("app");
        Map appConf = null;
        //查看渠道配置
        if (appConfs.containsKey(appId)){
            appConf = (Map)appConfs.get(appId);
        }
        //没有渠道配置就查看默认配置
        Map<String,Object> defConf = (Map<String,Object>)appConfs.get("default");
        if (appConf == null){
            appConf = defConf;
        }
        for (String key : defConf.keySet()){
            if (!appConf.containsKey(key)){
                appConf.put(key, defConf.get(key));
            }
        }
        //1、每个电话总发送量（不同模板） numPerMobile

        int numPerMobile = 0;
        if (appConf.containsKey("numPerMobile")){
            Integer.parseInt(appConf.get("numPerMobile").toString());
        }

        PushRecordSearchArgs args = new PushRecordSearchArgs();
        args.setAppId(appId);
        args.setAid(aid);
        args.setMinCreateTime(Utils.getBeginTimeOfDay(new Date()));
        args.setMaxCreateTime(Utils.getEndTimeOfDay(new Date()));
        args.setTo(to);
        int n = pushRecordDao.getRecordCount(args);
        if (n >= numPerMobile){
            logger.info("|check|numPerMobile:"+n+">="+numPerMobile);
            return false;
        }

        //2、每个客户ip总发送量（不同模板） numPerIp
        int numPerIp = Utils.parseInt(appConf.get("numPerIp"));
        args.setTo(null);
        args.setAppId(null);
        args.setIp(ip);
        n = pushRecordDao.getRecordCount(args);
        if (n >= numPerIp){
            logger.info("|check|numPerIp:"+n+">="+numPerIp);
            return false;
        }
        //3、每个模板发送量 numPerTpl
        int numPerTpl = Utils.parseInt(appConf.get("numPerTpl"));
        args.setIp(null);
        args.setMsgId(msgId);
        n = pushRecordDao.getRecordCount(args);
        if (n >= numPerTpl){
            logger.info("|check|numPerTpl:"+n+">="+numPerTpl);
            return false;
        }
        //4、所有模板总发送量 totalOfTpl
        int totalOfTpl = Utils.parseInt(appConf.get("totalOfTpl"));
        args.setMsgId(null);
        n = pushRecordDao.getRecordCount(args);
        if (n >= totalOfTpl){
            logger.info("|check|totalOfTpl:"+n+">="+totalOfTpl);
            return false;
        }
        return true;
    }

    public HttpResponse push(final PushApp pushApp, final PushMsgConf msgConf, final Map data, final String appId, final String ip){

        String to = null;
        if ( pushApp.getType().equalsIgnoreCase(PushApp.APP_TYPE_SMS) ){
            to = (String)data.get("mobile");
        }else{
            to =  (String)data.get("openId");
        }

        final PushService service = servicePool.get(pushApp.getSp());
        //校验
        boolean isValid = check(appId,pushApp.getId(),pushApp.getType(),to, msgConf.getId(),ip);
        if (!isValid){
            throw new DataException("auth.request.limit.exceed");
        }
        final String dest = to;
        taskExecutor.execute(new Runnable() {
            @Override
            public void run() {
                HttpResponse ret = service.send(pushApp, msgConf, data, ip);
                addRecord(appId,pushApp, msgConf, data, dest,ip, ret.isSuccess(),ret.getMsg());
            }
        });

        return HttpResponse.getSuccessResponse();
    }

    @Override
    public HttpResponse push(PushRecordSendArgs args) {
        String []a = args.getAppAlias().split(",");
        for (int i = 0; i< a.length; i++){
            List<PushApp> apps = pushAppDao.getAppListByAlias(a[i]);
            if( apps == null || apps.size() == 0 ){
                continue;
            }
            for (int j = 0; j < apps.size(); j++){
                PushApp pushApp = apps.get(j);
                PushMsgConf msgConf = pushMsgConfDao.getMsgConfByAlias(pushApp.getId(), args.getMsgAlias());
                if(msgConf == null){
                    continue;
                }
                HttpResponse r = push(pushApp, msgConf, args.getData(),args.getAppId(), args.getIp());
                if (!r.isSuccess()){
                    return r;
                }
                break;
            }
//            PushApp pushApp = pushAppDao.getAppByAlias(a[i]);
//            if(pushApp == null){
//                continue;
//            }
//            PushMsgConf msgConf = pushMsgConfDao.getMsgConfByAlias(pushApp.getId(), args.getMsgAlias());
//            if(msgConf == null){
//                continue;
//            }
//            HttpResponse r = push(pushApp, msgConf, args.getData(),args.getAppId(), args.getIp());
//            if (!r.isSuccess()){
//                return r;
//            }
        }
        return  HttpResponse.getSuccessResponse();

    }
}
